#include "SSBizTool.h"

#include <bondlib/BondCSIPriceInfo.h>
#include <bondlib/BondType.h>
#include <bondlib/QBIssuerInfo.h>

#include <QString>

#include "bondlib/BondCDCPriceInfo.h"
#include "uam/ServerTimeMgr.h"

namespace qb {
namespace biz {
std::string BuildIssuerName(const char *pszIssuerCode, bool eng) {
  std::string sName("");
  auto pIssuer = CQBIssuerInfo::instance().GetIssuerInfo(pszIssuerCode);
  if (pIssuer)
    sName = eng ? pIssuer->field((int)kIssuerInfo::Full_Name_E)
                : pIssuer->field((int)kIssuerInfo::Full_Name_C);

  return sName;
}

std::string BuildGuarantorName(const char *pszGuarantor, bool eng) {
  std::string sName("");
  QStringList vctCode = QString::fromLocal8Bit(pszGuarantor).split("|");
  for (auto itr = vctCode.begin(); itr != vctCode.end(); ++itr) {
    auto pIssuer = CQBIssuerInfo::instance().GetIssuerInfo(itr->toStdString());
    if (pIssuer) {
      std::string sTemp = eng ? pIssuer->field((int)kIssuerInfo::Full_Name_E)
                              : pIssuer->field((int)kIssuerInfo::Full_Name_C);
      if (!sTemp.empty()) {
        if (!sName.empty()) sName.append(";");
      }
      sName.append(sTemp);
    }
  }
  return sName;
}

std::string BuildBondTypeName(const char *pszSubTypeCode, const char *pszEntCor,
                              bool eng) {
  const CBondTypeV2 btv =
      CBondTypeMap::instance().GetType(pszSubTypeCode, pszEntCor);
  return eng ? btv.m_Name_E : btv.m_Name_C;
}

std::string BuildIssuerTag(const char *pszIssuerCode) {
  std::string sName("");
  auto pIssuer = CQBIssuerInfo::instance().GetIssuerInfo(pszIssuerCode);
  if (pIssuer) sName = pIssuer->field((int)kIssuerInfo::Issuer_tag);

  return sName;
}

namespace csi {
std::string FmtYield(std::string sCombondkey) {
  UINT nCSIType = CBondCSInfo::emCSITypeNull;
  return FmtYield(sCombondkey, nCSIType);
}

std::string FmtYield(std::string sCombondkey, UINT &nCSIType) {
  nCSIType = CBondCSInfo::emCSITypeNull;

  char szBuffer[32] = "--";

  xCSIUint_c xUnit;
  if (CBondCSInfo::instance().GetCsiUnit(sCombondkey, xUnit)) {
    if (xUnit.IsHaveYieldToExercise()) {
      nCSIType = CBondCSInfo::emCSITypeExercise;
    }

    if (xUnit.IsHaveYieldToMarturity()) {
      if (nCSIType == CBondCSInfo::emCSITypeExercise) {
        nCSIType = CBondCSInfo::emCSITypeCombine;
        FMTBUF(szBuffer, "%.4f/%.4f", xUnit.m_dYieldToExercise,
               xUnit.m_dYieldToMaturity);
      } else {
        nCSIType = CBondCSInfo::emCSITypeMaturity;
        FMTBUF(szBuffer, "%.4f", xUnit.m_dYieldToMaturity);
      }
    } else {
      if (nCSIType == CBondCSInfo::emCSITypeExercise) {
        FMTBUF(szBuffer, "%.4f", xUnit.m_dYieldToExercise);
      }
    }
  }

  return std::string(szBuffer);
}

std::string FmtCleanPrice(std::string sCombondkey) {
  char szBuffer[32] = "--";

  UINT nCSIType = CBondCSInfo::emCSITypeNull;

  xCSIUint_c xUnit;
  if (CBondCSInfo::instance().GetCsiUnit(sCombondkey, xUnit)) {
    if (xUnit.IsHaveCleanPriceExercise()) {
      nCSIType = CBondCSInfo::emCSITypeExercise;
    }

    if (xUnit.IsHaveCleanPriceMarturity()) {
      if (nCSIType == CBondCSInfo::emCSITypeExercise) {
        nCSIType = CBondCSInfo::emCSITypeCombine;
        FMTBUF(szBuffer, "%.4f/%.4f", xUnit.m_dCleanPriceExercise,
               xUnit.m_dCleanPriceMaturity);
      } else {
        nCSIType = CBondCSInfo::emCSITypeMaturity;
        FMTBUF(szBuffer, "%.4f", xUnit.m_dCleanPriceMaturity);
      }
    } else {
      if (nCSIType == CBondCSInfo::emCSITypeExercise) {
        FMTBUF(szBuffer, "%.4f", xUnit.m_dCleanPriceExercise);
      }
    }
  }

  return std::string(szBuffer);
}

std::string FmtDealMinusCSI(std::string sCombondkey,
                            std::string sDeal) {  // 成交-中证,此处值作为显示
  if (sDeal.size() <= 0) return "--";

  if (sDeal.compare("--") == 0) return "--";

  double taken = atof(sDeal.c_str());
  if (taken >= 30.0 || taken == 0.0) return "--";

  char buf[128] = "--";

  xCSIUint_c xUnit;
  if (CBondCSInfo::instance().GetCsiUnit(sCombondkey, xUnit)) {
    double dRet = _INVALID_CSI_VALUE;
    double dExercise = xUnit.IsHaveYieldToExercise() ? xUnit.m_dYieldToExercise
                                                     : _INVALID_CSI_VALUE;
    double dMaturity = xUnit.IsHaveYieldToMarturity() ? xUnit.m_dYieldToMaturity
                                                      : _INVALID_CSI_VALUE;

    if (dExercise > _INVALID_CSI_VALUE && dMaturity > _INVALID_CSI_VALUE) {
      dExercise = taken - dExercise;
      dMaturity = taken - dMaturity;
      dRet = abs(dExercise) < abs(dMaturity) ? dExercise : dMaturity;
    } else if (dExercise > _INVALID_CSI_VALUE) {
      dRet = taken - dExercise;
    } else if (dMaturity > _INVALID_CSI_VALUE) {
      dRet = taken - dMaturity;
    }

    FMTBUF(buf, "%.2f", dRet * 100);
  }

  return std::string(buf);
}

std::string FmtBidMinusCSI(
    const REPORT &report,
    const CBondInfo *pBond) {  // 可以改的更加标准一点，供cfets和broker共用
  if (strcmp(report.m_bidinfo.m_price_status, "0") == 0 ||
      strlen(report.m_bidinfo.m_yield_price) <= 0)
    return "--";

  xCSIUint_c xUnit;
  if (!CBondCSInfo::instance().GetCsiUnit(pBond->GetCombBondKey(), xUnit))
    return "--";

  if (!xUnit.IsHaveYieldToExercise() && !xUnit.IsHaveYieldToMarturity())
    return "--";

  char buf[128] = "--";

  double dRet = _INVALID_CSI_VALUE;
  double dExercise = xUnit.IsHaveYieldToExercise() ? xUnit.m_dYieldToExercise
                                                   : _INVALID_CSI_VALUE;
  double dMaturity = xUnit.IsHaveYieldToMarturity() ? xUnit.m_dYieldToMaturity
                                                    : _INVALID_CSI_VALUE;

  double dBidPrice = atof(report.m_bidinfo.m_yield_price);

  if (dExercise > _INVALID_CSI_VALUE && dMaturity > _INVALID_CSI_VALUE) {
    dExercise = dBidPrice - dExercise;
    dMaturity = dBidPrice - dMaturity;
    dRet = abs(dExercise) < abs(dMaturity) ? dExercise : dMaturity;
  } else if (dExercise > _INVALID_CSI_VALUE) {
    dRet = dBidPrice - dExercise;
  } else if (dMaturity > _INVALID_CSI_VALUE) {
    dRet = dBidPrice - dMaturity;
  }

  if (dRet > _INVALID_CSI_VALUE) FMTBUF(buf, "%.2f", dRet * 100);

  return std::string(buf);
}

std::string FmtBidMinusCSI(
    const CFETSQUOTE &report,
    const CBondInfo *pBond) {  // 可以改的更加标准一点，供cfets和broker共用
  xCSIUint_c xUnit;
  if (!CBondCSInfo::instance().GetCsiUnit(pBond->GetCombBondKey(), xUnit))
    return "--";

  if (!xUnit.IsHaveYieldToExercise() && !xUnit.IsHaveYieldToMarturity())
    return "--";

  if (strcmp(report.m_BidPriceYield, "0") == 0 ||
      strcmp(report.m_BidPriceYield, "bid") == 0 ||
      strcmp(report.m_BidPriceYield, "Bid") == 0 ||
      strlen(report.m_BidPriceYield) <= 0) {
    return "--";
  }

  char buf[128] = "--";

  double dRet = _INVALID_CSI_VALUE;
  double dExercise = xUnit.IsHaveYieldToExercise() ? xUnit.m_dYieldToExercise
                                                   : _INVALID_CSI_VALUE;
  double dMaturity = xUnit.IsHaveYieldToMarturity() ? xUnit.m_dYieldToMaturity
                                                    : _INVALID_CSI_VALUE;

  // double dBidPrice = atof(report.m_bidinfo.m_yield_price);
  double dBidPrice = atof(report.m_BidPriceYield);

  if (dExercise > _INVALID_CSI_VALUE && dMaturity > _INVALID_CSI_VALUE) {
    dExercise = dBidPrice - dExercise;
    dMaturity = dBidPrice - dMaturity;
    dRet = abs(dExercise) < abs(dMaturity) ? dExercise : dMaturity;
  } else if (dExercise > _INVALID_CSI_VALUE) {
    dRet = dBidPrice - dExercise;
  } else if (dMaturity > _INVALID_CSI_VALUE) {
    dRet = dBidPrice - dMaturity;
  }

  if (dRet > _INVALID_CSI_VALUE) FMTBUF(buf, "%.2f", dRet * 100);

  return std::string(buf);
}

std::string FmtCSIMinusOfr(
    const REPORT &report,
    const CBondInfo *pBond) {  // 可以改的更加标准一点，供cfets和broker共用

  if (strcmp(report.m_askinfo.m_price_status, "0") == 0 ||
      strlen(report.m_askinfo.m_yield_price) <= 0)
    return "--";

  xCSIUint_c xUnit;
  if (!CBondCSInfo::instance().GetCsiUnit(pBond->GetCombBondKey(), xUnit))
    return "--";

  double dOfrPrice = atof(report.m_askinfo.m_yield_price);

  int nQuoteType = atoi(report.m_askinfo.m_quotetype);
  if (nQuoteType != 3 &&
      (pBond->IsBondABS() ||
       pBond->IsTransBond()))  // quotetype不是收益率，仅ABS和可转债判定0-30
  {
    if (dOfrPrice <= 0.0 || dOfrPrice >= 30.0) return "--";
  }

  if (!xUnit.IsHaveYieldToExercise() && !xUnit.IsHaveYieldToMarturity())
    return "--";

  double dExercise = xUnit.IsHaveYieldToExercise() ? xUnit.m_dYieldToExercise
                                                   : _INVALID_CSI_VALUE;
  double dMaturity = xUnit.IsHaveYieldToMarturity() ? xUnit.m_dYieldToMaturity
                                                    : _INVALID_CSI_VALUE;

  char buf[128] = "--";

  double dRet = 0.000000;
  if (dExercise > _INVALID_CSI_VALUE && dMaturity > _INVALID_CSI_VALUE) {
    dExercise = dExercise - dOfrPrice;
    dMaturity = dMaturity - dOfrPrice;
    dRet = abs(dExercise) < abs(dMaturity) ? dExercise : dMaturity;
  } else if (dExercise > _INVALID_CSI_VALUE) {
    dRet = dExercise - dOfrPrice;
  } else if (dMaturity > _INVALID_CSI_VALUE) {
    dRet = dMaturity - dOfrPrice;
  }

  if (dRet > _INVALID_CSI_VALUE) FMTBUF(buf, "%.2f", dRet * 100);

  return std::string(buf);
}

std::string FmtCSIMinusOfr(
    const CFETSQUOTE &report,
    const CBondInfo *pBond) {  // 可以改的更加标准一点，供cfets和broker共用
  xCSIUint_c xUnit;
  if (!CBondCSInfo::instance().GetCsiUnit(pBond->GetCombBondKey(), xUnit))
    return "--";

  if (!xUnit.IsHaveYieldToExercise() && !xUnit.IsHaveYieldToMarturity())
    return "--";

  if (strcmp(report.m_OfrPriceYield, "0") == 0 ||
      strcmp(report.m_OfrPriceYield, "ofr") == 0 ||
      strcmp(report.m_OfrPriceYield, "Ofr") == 0 ||
      strlen(report.m_OfrPriceYield) <= 0) {
    return "--";
  }

  // double dOfrPrice = atof(report.m_askinfo.m_yield_price);
  double dOfrPrice = atof(report.m_OfrPriceYield);

  // int nQuoteType = atoi(report.m_askinfo.m_quotetype);
  // if (nQuoteType != 3 && (pBond->IsBondABS() ||
  // pBond->IsTransBond()))//quotetype不是收益率，仅ABS和可转债判定0-30
  //{
  //	if (dOfrPrice <= 0.0 || dOfrPrice >= 30.0)
  //		return "--";
  // }

  double dExercise = xUnit.IsHaveYieldToExercise() ? xUnit.m_dYieldToExercise
                                                   : _INVALID_CSI_VALUE;
  double dMaturity = xUnit.IsHaveYieldToMarturity() ? xUnit.m_dYieldToMaturity
                                                    : _INVALID_CSI_VALUE;

  char buf[128] = "--";

  double dRet = 0.000000;
  if (dExercise > _INVALID_CSI_VALUE && dMaturity > _INVALID_CSI_VALUE) {
    dExercise = dExercise - dOfrPrice;
    dMaturity = dMaturity - dOfrPrice;
    dRet = abs(dExercise) < abs(dMaturity) ? dExercise : dMaturity;
  } else if (dExercise > _INVALID_CSI_VALUE) {
    dRet = dExercise - dOfrPrice;
  } else if (dMaturity > _INVALID_CSI_VALUE) {
    dRet = dMaturity - dOfrPrice;
  }

  if (dRet > _INVALID_CSI_VALUE) FMTBUF(buf, "%.2f", dRet * 100);

  return std::string(buf);
}

std::string FmtCSIMinusCDC(const CBondInfo *pBond, const int nBondIndex,
                           bool bIsCDCAuthValid) {
  Q_ASSERT(pBond != NULL);

  double dCdcExercise = INVALID_CDC_VALUE;
  double dCdcMaturity = INVALID_CDC_VALUE;
  CBondCDCPriceInfo::instance().GetExerciseAndMaturity(
      bIsCDCAuthValid, nBondIndex, dCdcExercise, dCdcMaturity);

  double dCsiExercise = _INVALID_CSI_VALUE;
  double dCsiMaturity = _INVALID_CSI_VALUE;
  xCSIUint_c xcsi;
  if (CBondCSInfo::instance().GetCsiUnit(pBond->GetCombBondKey(), xcsi)) {
    dCsiExercise = xcsi.m_dYieldToExercise;
    dCsiMaturity = xcsi.m_dYieldToMaturity;
  }

  bool bExerciseValid = false;
  char szExercise[32] = {0};
  if (dCdcExercise <= INVALID_CDC_VALUE || dCsiExercise <= _INVALID_CSI_VALUE) {
    FMTBUF(szExercise, "%s", "--");
  } else {
    bExerciseValid = true;
    FMTBUF(szExercise, "%.2f", (dCsiExercise - dCdcExercise) * 100);
  }

  bool bMaturityValid = false;
  std::string sExercise;
  char szMaturity[32] = {0};
  if (dCdcMaturity <= INVALID_CDC_VALUE || dCsiMaturity <= _INVALID_CSI_VALUE) {
    FMTBUF(szMaturity, "%s", "--");
  } else {
    bMaturityValid = true;
    FMTBUF(szMaturity, "%.2f", (dCsiMaturity - dCdcMaturity) * 100);
  }

  char szRet[32] = {0};
  if (bExerciseValid && bMaturityValid) {
    FMTBUF(szRet, "%s/%s", szExercise, szMaturity);
  } else if (bExerciseValid) {
    FMTBUF(szRet, "%s", szExercise);
  } else if (bMaturityValid) {
    FMTBUF(szRet, "%s", szMaturity);
  } else {
    FMTBUF(szRet, "%s", "--");
  }

  return szRet;
}
}  // namespace csi
}  // namespace biz
}  // namespace qb